
/**  
* @Title: ImageUtil.java
* @Package com.utils.file
* @Description: 
* @author likai
* @date 2018年1月9日
* @version V1.0  
*/

package com.utils.file;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.supers.exception.ExceptionUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * @ClassName: ImageUtil
 * @Description: 图片处理工具(base64转换，图片合成、拼接、截图、插入文字,添加圆角,图片缩放)
 * @author likai
 * @date 2018年1月9日
 *
 */
@SuppressWarnings("restriction")
public class ImageUtil {
	public static Logger log = LoggerFactory.getLogger(ImageUtil.class);
	/*------------------------------------------------------base64转换----------------------------------------------------*/

	/**
	 * @Description: 将base64编码字符串转换为图片
	 * @param imgStr:base64编码字符串
	 * @param path: 图片路径-具体到文件
	 * @return
	 */
	public static boolean convertBase64ToImage(String imgStr, String path) {
		if (imgStr == null) {
			return false;
		}
		BASE64Decoder decoder = new BASE64Decoder();
		imgStr = imgStr.substring(imgStr.indexOf(",") + 1, imgStr.length());
		try {
			// 解密
			byte[] b = decoder.decodeBuffer(imgStr);
			// 处理数据
			for (int i = 0; i < b.length; ++i) {
				if (b[i] < 0) {
					b[i] += 256;
				}
			}
			File file = new File(path);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			OutputStream out = new FileOutputStream(path);
			out.write(b);
			out.flush();
			out.close();
			return true;
		} catch (Exception e) {
			log.info(ExceptionUtils.getExceptionMessage(e));
			return false;
		}
	}

	/**
	 * @Description: 将图片转换为base64编码字符串
	 * @Author:
	 * @CreateTime:
	 * @return
	 */
	public static String convertImageToBase64(String imgFile) {
		InputStream inputStream = null;
		byte[] data = null;
		try {
			inputStream = new FileInputStream(imgFile);
			data = new byte[inputStream.available()];
			inputStream.read(data);
			inputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 加密
		BASE64Encoder encoder = new BASE64Encoder();
		return encoder.encode(data);
	}

	/*------------------------------------------------------图片合成、拼接----------------------------------------------------*/

	/**
	 * @Description:截图
	 * @param srcFile源图片、targetFile截好后图片全名、startAcross
	 *            开始截取位置横坐标、StartEndlong开始截图位置纵坐标、width截取的长，hight截取的高
	 */
	public static void cutImage(String srcFile, String targetFile, int startAcross, int StartEndlong, int width,
			int hight) throws Exception {
		// 取得图片读入器
		Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
		ImageReader reader = readers.next();
		// 取得图片读入流
		InputStream source = new FileInputStream(srcFile);
		ImageInputStream iis = ImageIO.createImageInputStream(source);
		reader.setInput(iis, true);
		// 图片参数对象
		ImageReadParam param = reader.getDefaultReadParam();
		Rectangle rect = new Rectangle(startAcross, StartEndlong, width, hight);
		param.setSourceRegion(rect);
		BufferedImage bi = reader.read(0, param);
		ImageIO.write(bi, targetFile.split("\\.")[1], new File(targetFile));
	}

	/**
	 * @Description:图片拼接 （注意：必须两张图片长宽一致哦）
	 * @param files要拼接的文件列表,type:1横向拼接，
	 *            2 纵向拼接
	 */
	public static void mergeImage(String[] files, int type, String targetFile) {
		int len = files.length;
		if (len < 1) {
			throw new RuntimeException("图片数量小于1");
		}
		File[] src = new File[len];
		BufferedImage[] images = new BufferedImage[len];
		int[][] ImageArrays = new int[len][];
		for (int i = 0; i < len; i++) {
			try {
				src[i] = new File(files[i]);
				images[i] = ImageIO.read(src[i]);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
			int width = images[i].getWidth();
			int height = images[i].getHeight();
			ImageArrays[i] = new int[width * height];
			ImageArrays[i] = images[i].getRGB(0, 0, width, height, ImageArrays[i], 0, width);
		}
		int newHeight = 0;
		int newWidth = 0;
		for (int i = 0; i < images.length; i++) {
			// 横向
			if (type == 1) {
				newHeight = newHeight > images[i].getHeight() ? newHeight : images[i].getHeight();
				newWidth += images[i].getWidth();
			} else if (type == 2) {// 纵向
				newWidth = newWidth > images[i].getWidth() ? newWidth : images[i].getWidth();
				newHeight += images[i].getHeight();
			}
		}
		if (type == 1 && newWidth < 1) {
			return;
		}
		if (type == 2 && newHeight < 1) {
			return;
		}

		// 生成新图片
		try {
			BufferedImage ImageNew = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
			int height_i = 0;
			int width_i = 0;
			for (int i = 0; i < images.length; i++) {
				if (type == 1) {
					ImageNew.setRGB(width_i, 0, images[i].getWidth(), newHeight, ImageArrays[i], 0,
							images[i].getWidth());
					width_i += images[i].getWidth();
				} else if (type == 2) {
					ImageNew.setRGB(0, height_i, newWidth, images[i].getHeight(), ImageArrays[i], 0, newWidth);
					height_i += images[i].getHeight();
				}
			}
			// 输出想要的图片
			ImageIO.write(ImageNew, targetFile.split("\\.")[1], new File(targetFile));

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @Description:小图片贴到大图片形成一张图
	 * @param bigPath大图片路径,smallPath小图片路径,outFile生成文件路径,
	 *          x 小图左边距离大图片左边位置 y小图上边距离大图片上边距离
	 *            smallWidth:合成的小图片宽度， smallHeight合成的小图片高度
	 * @return 
	 */
	public static final BufferedImage overlapImage(BufferedImage bigImg, BufferedImage smallImg, int x, int y,
			int smallWidth, int smallHeight) {
		try {
			Graphics2D g = bigImg.createGraphics();
			/*int x = (bigImg.getWidth() - smallImg.getWidth()) / (xw);
			int y = (bigImg.getHeight() - smallImg.getHeight()) / (yh);*/
			if (smallWidth == 0) {
				smallWidth = smallImg.getWidth();
			}
			if (smallHeight == 0) {
				smallHeight = smallImg.getHeight();
			}
			g.drawImage(smallImg, x, y, smallWidth, smallHeight, null);
			g.dispose();
			return bigImg;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/*
	 * public static void main(String[] args) {
	 * overlapImage("E:/Downloads/1.jpg", "E:/Downloads/100.png",
	 * "E:/Downloads/101.png",4,2); }
	 */

	/*------------------------------------------------------图片插入文字----------------------------------------------------*/

	/**
	 * @Description:向图片添加一行文字
	 * 
	 * @param img图片,content文字内容
	 *            x文字距离左边距离，y文字距离顶部距离
	 */
	public static BufferedImage modifyImage(BufferedImage img, String content,int x, int y, FontStyle fontStyle) {
		try {
			Font font = new Font(fontStyle.getFontStyle(), fontStyle.getConstant(), fontStyle.getFontsize());//
			Graphics2D g = img.createGraphics();
			g.setBackground(fontStyle.getBackgroundColor());// 设置字体背景颜色
			g.setColor(fontStyle.getFontColor());// 设置字体颜色
			g.setFont(font);
			if (content != null) {
				g.drawString(content, x, y);
			}
			g.dispose();
		} catch (Exception e) {
			log.info(e.getMessage());
			;
		}

		return img;
	}

	/**
	 * @Description:向图片添加多行文字
	 * 
	 * @param img图片,contentArr文字内容数组
	 *            xory：true表示将内容在一行中输出；false表示将内容多行输出 xw文字在大图片x轴中心位置(xw分之一距离)
	 *            yh文字在大图片y轴中心位置(yh分之一距离)
	 */
	public static BufferedImage modifyImage(BufferedImage img, Object[] contentArr, int xw, int yh, boolean xory,
			FontStyle fontStyle) {
		try {
			Font font = new Font(fontStyle.getFontStyle(), fontStyle.getConstant(), fontStyle.getFontsize());//
			int w = img.getWidth() / xw;
			int h = (img.getHeight() - fontStyle.getFontsize()) / yh;
			Graphics2D g = img.createGraphics();
			g.setBackground(fontStyle.getBackgroundColor());// 设置字体背景颜色
			g.setColor(fontStyle.getFontColor());// 设置字体颜色
			g.setFont(font);
			if (contentArr != null) {
				int arrlen = contentArr.length;
				if (xory) {
					StringBuffer content = new StringBuffer();
					// 内容一行输出
					for (int i = 0; i < arrlen; i++) {
						content.append(" ").append(contentArr[i].toString());
					}
					g.drawString(content.toString(), w, h);
				} else {
					// 内容多行输出
					for (int i = 0; i < arrlen; i++) {
						g.drawString(contentArr[i].toString(), w, h);
						h += fontStyle.getFontsize() + 2;// 重新计算文本输出位置
					}
				}
			}
			g.dispose();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}

		return img;
	}

	/**
	 * 导入本地图片到缓冲区
	 */
	public static BufferedImage loadImageLocal(String localImagePath) {
		try {
			return ImageIO.read(new File(localImagePath));
		} catch (IOException e) {
		}
		return null;
	}

	/**
	 * 导入网络图片到缓冲区
	 */
	public static BufferedImage loadImageUrl(String webImagePath) {
		try {
			URL url = new URL(webImagePath);
			return ImageIO.read(url);
		} catch (IOException e) {
		}
		return null;
	}

	/**
	 * 生成新图片到本地
	 */
	public static void writeImageLocal(String newImage, BufferedImage img) {
		if (newImage != null && img != null) {
			try {
				File outputfile = new File(newImage);
				ImageIO.write(img, "jpg", outputfile);
			} catch (IOException e) {
			}
		}
	}

	/*------------------------------------------------------添加圆角和缩放----------------------------------------------------*/

	/** 
     * 针对高度与宽度进行等比缩放 
     * 
     * @param img 
     * @param maxSize 要缩放到的尺寸 
     * @param type 1:高度与宽度的最大值为maxSize进行等比缩放 , 2:高度与宽度的最小值为maxSize进行等比缩放 
     * @return 
     */  
    private static Image getScaledImage(BufferedImage img, int maxSize, int type) {  
        int w0 = img.getWidth();  
        int h0 = img.getHeight();  
        int w = w0;  
        int h = h0;  
        if (type == 1) {  
            w = w0 > h0 ? maxSize : (maxSize * w0 / h0);  
            h = w0 > h0 ? (maxSize * h0 / w0) : maxSize;  
        } else if (type == 2) {  
            w = w0 > h0 ? (maxSize * w0 / h0) : maxSize;  
            h = w0 > h0 ? maxSize : (maxSize * h0 / w0);  
        }  
        Image image = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);  
        BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);  
        Graphics2D g = result.createGraphics();  
        g.drawImage(image, 0, 0, null);//在适当的位置画出  
        return result;  
    }  
  
   
    
    /** 
     * 先按最小宽高为size等比例绽放, 然后图像居中抠出直径为size的圆形图像 
     * 
     * @param img 
     * @param size 要缩放到的尺寸 和圆角直径
     * @return 
     */  
    public static BufferedImage getRoundedImage(BufferedImage img, int size,Color color) {  
        return getRoundedImage(img, size, size / 2, 2,color);  
    }  
  
    
   
    /** 
     * 先按最小宽高为size等比例绽放, 然后图像居中抠出半径为radius的圆形图像 
     * 
     * @param img 
     * @param size 要缩放到的尺寸 
     * @param radius 圆角半径 
     * @param type 1:高度与宽度的最大值为maxSize进行等比缩放 , 2:高度与宽度的最小值为maxSize进行等比缩放 
     * @param color圆角填充色
     * @return 
     */  
    public static BufferedImage getRoundedImage(BufferedImage img, int size, int radius, int type,Color color) {  
  
        BufferedImage result = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);  
        Graphics2D g = result.createGraphics();  
  
        //先按最小宽高为size等比例绽放, 然后图像居中抠出直径为size的圆形图像  
        Image fixedImg = getScaledImage(img, size, type); //等比缩放
        g.drawImage(fixedImg, (size - fixedImg.getWidth(null)) / 2, (size - fixedImg.getHeight(null)) / 2, null);//在适当的位置画出  
        //圆角  
        if (radius > 0) {  
            RoundRectangle2D round = new RoundRectangle2D.Double(0, 0, size, size, radius * 2, radius * 2);  
            Area clear = new Area(new Rectangle(0, 0, size, size));  
            clear.subtract(new Area(round)); 
            g.setColor(color);
            //抗锯齿  
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
            g.fill(clear);  
            g.dispose();  
        }  
        //如果图像是透明的，就丢弃Alpha通道  
        if (result.getTransparency() == Transparency.TRANSLUCENT) {  
        	result = get24BitImage(result);  
        }  
        return result;  
    }  
  
    /** 
     * 使用删除alpha值的方式去掉图像的alpha通道 
     * 
     * @param $image 
     * @return 
     */  
    private static BufferedImage get24BitImage(BufferedImage $image) {  
        int __w = $image.getWidth();  
        int __h = $image.getHeight();  
        int[] __imgARGB = getRGBs($image.getRGB(0, 0, __w, __h, null, 0, __w));  
        BufferedImage __newImg = new BufferedImage(__w, __h, BufferedImage.TYPE_INT_RGB);  
        __newImg.setRGB(0, 0, __w, __h, __imgARGB, 0, __w);  
        return __newImg;  
    }  
  
    /** 
     * 使用绘制的方式去掉图像的alpha值 
     * 
     * @param $image 
     * @param $bgColor 
     * @return 
     */  
    @SuppressWarnings("unused")
	private static BufferedImage get24BitImage(BufferedImage $image, Color $bgColor) {  
        int $w = $image.getWidth();  
        int $h = $image.getHeight();  
        BufferedImage img = new BufferedImage($w, $h, BufferedImage.TYPE_INT_RGB);  
        Graphics2D g = img.createGraphics();  
        g.setColor($bgColor);  
        g.fillRect(0, 0, $w, $h);  
        g.drawRenderedImage($image, null);  
        g.dispose();  
        return img;  
    }  
  
    /** 
     * 将32位色彩转换成24位色彩（丢弃Alpha通道） 
     * 
     * @param $argb 
     * @return 
     */  
    private static int[] getRGBs(int[] $argb) {  
        int[] __rgbs = new int[$argb.length];  
        for (int i = 0; i < $argb.length; i++) {  
            __rgbs[i] = $argb[i] & 0xFFFFFF;  
        }  
        return __rgbs;  
    }  

    
    /** 
     * 圆形图片裁剪
     * 
     * @param iamge 源文件，cornerRadius圆周长
     * @param $bgColor 
     * @return 
     */  

    public static BufferedImage makeRoundedCornerImg( BufferedImage image,int cornerRadius) throws IOException {
        int w = image.getWidth();
        int h = image.getHeight();
        BufferedImage output = new BufferedImage(w, h,
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = output.createGraphics();
        g2.setComposite(AlphaComposite.Src);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.WHITE);
        g2.fill(new RoundRectangle2D.Float(0, 0, w, h, cornerRadius,
                cornerRadius));
        g2.setComposite(AlphaComposite.SrcAtop);
        g2.drawImage(image, 0, 0, null);

        g2.dispose();
        
        return output;
    }
   
    public static void main(String[] args) throws IOException {  
    	File slogoFile = new File("E:/Downloads/2.jpg");  
    	BufferedImage target=ImageIO.read(slogoFile);
    	BufferedImage logo=makeRoundedCornerImg(target, target.getWidth());
    	
    	File backImage = new File("E:/Downloads/100.jpg");  
        BufferedImage backImageIo=ImageIO.read(backImage);
        backImageIo=overlapImage(backImageIo, logo,  (backImageIo.getWidth() - 216)/2, 420, 216, 216);
    	File head = new File("E:/Downloads/0.jpg");  
        BufferedImage headIo=ImageIO.read(head);
        headIo=getRoundedImage(headIo, 96, 10, 2,new Color(217,89,64));
        backImageIo=overlapImage(backImageIo, headIo,  (backImageIo.getWidth() - 96)/2, 60, 96, 96);
        FontStyle fontStyle=new FontStyle("微软雅黑", 48,new Color(255,223,177) );
        backImageIo=modifyImage(backImageIo, "我是中国人啊我是中国人啊...",20,  300,fontStyle);
        writeImageLocal("E:/Downloads/101.jpg", backImageIo);
    }  
}
